package com.example.demo.jwt;

import cn.hutool.core.codec.Base64;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * @author zhanpengguo
 * @date 2019-07-04 11:00
 */
@Component
public class JWTUtil {

    private static final Logger logger = LoggerFactory.getLogger(JWTUtil.class);

    /**
     * 过期时间改为从配置文件获取
     */
    private static String accessTokenExpireTime;

    /**
     * JWT认证加密私钥(Base64加密)
     */
    private static String encryptJWTKey;

    @Value("${accessTokenExpireTime}")
    public void setAccessTokenExpireTime(String accessTokenExpireTime) {
        JWTUtil.accessTokenExpireTime = accessTokenExpireTime;
    }

    @Value("${encryptJWTKey}")
    public void setEncryptJWTKey(String encryptJWTKey) {
        JWTUtil.encryptJWTKey = encryptJWTKey;
    }

    /**
     * 校验token
     * @param token
     * @return
     */
    public static boolean verify(String token) throws AuthenticationException {
        String username = getUsername(token);
        String secret = Base64.decodeStr(username + encryptJWTKey);
        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256(secret);
        } catch (UnsupportedEncodingException e) {
            logger.error("token不正常",e);
            return false;
        }
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        jwtVerifier.verify(token);
        return true;
    }

    /**
     * 获取用户名
     * @param token
     * @return
     */
    public static String getUsername(String token){
        try {
            DecodedJWT decode = JWT.decode(token);
            return decode.getClaim(JWTConstant.USERNAME).asString();
        }catch (Exception e){
            logger.error("获取用户名失败：",e);
            return null;
        }
    }

    /**
     * 生成token
     * @param username
     * @return
     */
    public static String sign(String username,String currentMillients){
        try {
            //过期时间
            Date date = new Date(System.currentTimeMillis() + Long.parseLong(accessTokenExpireTime) * 1000);
            String secret = Base64.decodeStr(username + encryptJWTKey);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            String sign = JWT.create()
                    .withClaim(JWTConstant.USERNAME, username)
                    .withClaim(JWTConstant.CLAIM_CURRENT,currentMillients)
                    .withExpiresAt(date)
                    .sign(algorithm);
            return sign;
        }catch (Exception e){
            logger.error("签名错误：",e);
            return null;
        }
    }


    /**
     * 获取token中存的值
     * @param token
     * @param claim
     * @return
     */
    public static String getClaim(String token, String claim) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            // 只能输出String类型，如果是其他类型返回null
            return jwt.getClaim(claim).asString();
        } catch (JWTDecodeException e) {
            logger.error("解密Token中的公共信息出现异常:" + e.getMessage());
            throw new RuntimeException("解密Token中的公共信息出现异常:" + e.getMessage());
        }
    }
}
